package com.app.happybirds;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Calendar;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.app.happybirds.R.id;
import com.app.happybirds.quickmenu.QuickAction;

public class Report extends Activity implements LocationListener{

	int RESULT_FILE = 1;
	File file;
	String date;
	String latit;
	String longit;
	TaskSendReport taskSendReport;
	ProgressDialog progress;
	String email;
	SharedPreferences prefs;
	Location locationNow;
	LocationManager locationManager;
	
	public static final int TYPE_HANDLER_MENU_DATETIME = 1;
	public static final int TYPE_HANDLER_MENU_MAKEPHOTO = 2;
	public static final int TYPE_HANDLER_MENU_CHOOSEPHOTO = 3;
	public static final int TYPE_HANDLER_MENU_POSITION = 4;
	public static final int TYPE_HANDLER_ERROR_SEND_REPORT = -1;
	public static final int TYPE_HANDLER_SUCCESS_SEND_REPORT = 5;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.report);
		
		Calendar calend = Calendar.getInstance();
		
		date = calend.get(Calendar.YEAR)+"-"+calend.get(Calendar.MONTH)+"-"+calend.get(Calendar.DAY_OF_MONTH)
				+" "+calend.get(Calendar.HOUR_OF_DAY)+":"+calend.get(Calendar.MINUTE)+":"+calend.get(Calendar.SECOND);
	
		changePosition(0, 0);
		changeDate(date);
		
		prefs = getSharedPreferences("DataSaved", Context.MODE_PRIVATE);
		
		email = prefs.getString("EmailUser", "");
		
		progress = new ProgressDialog(this);
		progress.setProgress(ProgressDialog.STYLE_SPINNER);
		
		locationManager = (LocationManager) Report.this.getSystemService(Context.LOCATION_SERVICE);
		locationNow = locationManager.getLastKnownLocation(locationManager.getBestProvider(new Criteria(), false));		
		
		findViewById(id.buttonBack_report).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {				
				
				finish();
				
			}
		});
	
		findViewById(id.buttonPhoto_report).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				
				QuickAction quickMenuPhoto = new QuickAction(Report.this, handlReport);				
				quickMenuPhoto.addQuickPhotoMenu();
				quickMenuPhoto.show(v);
			}
		});
		
		findViewById(id.buttonTime_report).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				
				QuickAction quickMenuPhoto = new QuickAction(Report.this, handlReport);				
				quickMenuPhoto.addQuickOrarioMenu();
				quickMenuPhoto.show(v);
			}
		});
		
		findViewById(id.buttonSend_report).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				progress.show();
				
				if (taskSendReport != null)
					taskSendReport.cancel(true);
	
				taskSendReport = new TaskSendReport(file, email, 
						((EditText)findViewById(id.textMessage_report)).getText().toString(), 
						latit, longit, 
						((EditText)findViewById(id.textSpecies_report)).getText().toString(), 
						date,handlReport);
				taskSendReport.execute();
			}
		});
		
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		
		locationManager.removeUpdates(this);
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 2000, 0, this);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, this);
		if (locationNow != null)
			changePosition(locationNow.getLatitude(), locationNow.getLatitude());
	}
	
	void changePosition(double lat,double lon){
		latit = String.valueOf(lat);
		longit = String.valueOf(lon);
		
		((TextView)findViewById(id.textPosition_report)).setText("Position: "+latit+" "+longit);
	}
	
	void changeDate(String newDate){
		date = newDate;
		
		((TextView)findViewById(id.textTime_report)).setText("Date: "+date);
	}
	
	public String getRealPathFromURI(Uri contentUri) {
        // can post image
        String [] proj={MediaStore.Images.Media.DATA};
        Cursor cursor = managedQuery( contentUri,
                        proj, // Which columns to return
                        null,       // WHERE clause; which rows to return (all rows)
                        null,       // WHERE clause selection arguments (none)
                        null); // Order-by clause (ascending by name)
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();

        return cursor.getString(column_index);
	}
	
	File uriToFile(Uri uri){
		
		File fileResFile = null;

		if (uri.toString().contains("content")){
    		
			String urinew = "file://"+getRealPathFromURI(uri);

			try {
				fileResFile = new File(new URI (urinew));
			} catch (URISyntaxException e) {
				e.printStackTrace(); 
				Toast.makeText(Report.this,"Error loading file.. :S", Toast.LENGTH_LONG).show();
			}		  
        } else
			try {
				fileResFile = new File(new URI(uri.toString()));
			} catch (URISyntaxException e) {
				e.printStackTrace();
				Toast.makeText(Report.this,"Error loading file.. :S", Toast.LENGTH_LONG).show();
			}
		
		return fileResFile;
	}
	

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		if (data == null)
			return;
		
		if (requestCode == RESULT_FILE && resultCode != Activity.RESULT_CANCELED) {			
			Uri fileUri = data.getData();

			file = uriToFile(fileUri);
			if (file != null){
				((ImageView)findViewById(id.viewImageUpload_report)).setImageBitmap(BitmapFactory.decodeFile(file.getAbsolutePath()));
			}

			else {
				Toast.makeText(Report.this,"Error loading file.. :S", Toast.LENGTH_LONG).show();
			}
			
		}
	}
	
	Handler handlReport = new Handler(){
		
		public void handleMessage(Message msg) {
			
			switch (msg.what) {
			case TYPE_HANDLER_MENU_CHOOSEPHOTO:
				Intent intent = new Intent();
				intent.setType("image/*");
				intent.setAction(Intent.ACTION_GET_CONTENT);			
				startActivityForResult(Intent.createChooser(intent, "Complete action using"),RESULT_FILE);
				break;

			case TYPE_HANDLER_MENU_MAKEPHOTO:
				Toast.makeText(Report.this, "Not implemented...", Toast.LENGTH_SHORT).show(); //TODO
				break;
				
			case TYPE_HANDLER_MENU_DATETIME:
				date = (String) msg.obj;
				changeDate(date);
				break;
				
			case TYPE_HANDLER_MENU_POSITION:
				//TODO INIZIALIZZARE LOCATION MANAGER
				break;
				
			case TYPE_HANDLER_ERROR_SEND_REPORT:
				progress.dismiss();
				Toast.makeText(Report.this, "Error uploading report. Please try again.\n(Are you connected?)", Toast.LENGTH_SHORT).show();
				break;
				
			case TYPE_HANDLER_SUCCESS_SEND_REPORT:
				progress.dismiss();
				Toast.makeText(Report.this, "Report sent with success!. Thankyou :)", Toast.LENGTH_SHORT).show();
				break;
			}
			
		}
	};
	
private boolean isBetterLocation(Location location, Location currentBestLocation) {
		
		final int TWO_MINUTES = 1000*60*2;
		
	    if (currentBestLocation == null) {
	        // A new location is always better than no location
	        return true;
	    }

	    // Check whether the new location fix is newer or older
	    long timeDelta = location.getTime() - currentBestLocation.getTime();
	    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
	    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
	    boolean isNewer = timeDelta > 0;

	    // If it's been more than two minutes since the current location, use the new location
	    // because the user has likely moved
	    if (isSignificantlyNewer) {
	        return true;
	    // If the new location is more than two minutes older, it must be worse
	    } else if (isSignificantlyOlder) {
	        return false;
	    }

	    // Check whether the new location fix is more or less accurate
	    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;
	    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

	    // Check if the old and new location are from the same provider
	    boolean isFromSameProvider = isSameProvider(location.getProvider(),
	            currentBestLocation.getProvider());

	    // Determine location quality using a combination of timeliness and accuracy
	    if (isMoreAccurate) {
	        return true;
	    } else if (isNewer && !isLessAccurate) {
	        return true;
	    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
	        return true;
	    }
	    return false;
	}

	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
     	 return provider2 == null;
		}
		return provider1.equals(provider2);
	}

	@Override
	public void onLocationChanged(Location location) {
		if (isBetterLocation(location, locationNow)){
			locationNow = location;
			changePosition(locationNow.getLatitude(),locationNow.getLongitude());
		}
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		
	}
	
	class TaskSendReport extends AsyncTask<String, String, String>{

		
		private final File fileToUpload;
		private final String email;
		private final String message;
		private final String lat;
		private final String lon;
		private final String specie;
		private final String date;
		private final Handler handl;


		public TaskSendReport(File fileToUpload, String email,String message,String lat,String lon,String specie,String date,Handler handl) {
			this.fileToUpload = fileToUpload;
			this.email = email;
			this.message = message;
			this.lat = lat;
			this.lon = lon;
			this.specie = specie;
			this.date = date;
			this.handl = handl;
		}
		
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			
			if (result == null)
				handl.sendEmptyMessage(Report.TYPE_HANDLER_ERROR_SEND_REPORT);
			else
				handl.sendEmptyMessage(Report.TYPE_HANDLER_SUCCESS_SEND_REPORT);
		}
		
		@Override
		protected String doInBackground(String... params) {
			
			System.out.println("dati "+email+" "+lat+" "+date);
			
			HttpURLConnection conn = null;
			DataOutputStream dos = null;

			String lineEnd = "\n";
			String twoHyphens = "--";
			String boundary = "*****";
			int bytesRead, bytesAvailable, bufferSize;
			byte[] buffer;
			int maxBufferSize = 512 * 512;

			String charset = "UTF-8";

			String upLoadServerUri = "http://10.0.2.2/index/test-upload";
			String fileName = fileToUpload.getName();

			try {

				FileInputStream fileInputStream = new FileInputStream(fileToUpload);

				URL url = new URL(upLoadServerUri);
				conn = (HttpURLConnection) url.openConnection();
				conn.setDoInput(true);
				conn.setDoOutput(true);
				conn.setUseCaches(false);

				conn.setRequestMethod("POST");
				conn.setRequestProperty("Connection", "Keep-Alive");
				conn.setRequestProperty("Accept-Charset", charset);
				conn.setRequestProperty("ENCTYPE", "multipart/form-data");
				conn.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary);
//				conn.setRequestProperty("file_name", fileName);
				
				dos = new DataOutputStream(conn.getOutputStream());
				
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"user_email\"" + lineEnd );
				dos.writeBytes(URLEncoder.encode(email)+lineEnd);
				
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"latitude\"" + lineEnd);
				dos.writeBytes(URLEncoder.encode(lat)+lineEnd);
				
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"longitude\"" + lineEnd);
				dos.writeBytes(URLEncoder.encode(lon)+lineEnd);
				
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"species\"" + lineEnd);
				dos.writeBytes(URLEncoder.encode(specie)+lineEnd);
				
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"report_datetime\"" + lineEnd);
				dos.writeBytes(URLEncoder.encode(date)+lineEnd);
			
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"photo\"; filename=\""+ fileName + "\"" + lineEnd);			
				dos.writeBytes("Content-Type: image/*"+lineEnd+lineEnd);
				
				//scrittura file
				buffer = new byte[maxBufferSize];

				do {

					bytesAvailable = fileInputStream.available();
					bufferSize = Math.min(bytesAvailable, maxBufferSize);
					bytesRead = fileInputStream.read(buffer, 0, bufferSize);
					dos.write(buffer, 0, bytesRead);
			
				} while (bytesRead > 0);


				// send multipart form data necesssary after file data...
				dos.writeBytes(lineEnd);
			
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"message\""+ lineEnd);
				dos.writeBytes(URLEncoder.encode(message)+lineEnd);
				dos.writeBytes(twoHyphens + boundary + lineEnd);
	
				// close streams
				fileInputStream.close();
				dos.flush();
				dos.close();
			} catch (Exception ex) {
				ex.printStackTrace();
				return null;
			}
			
			return "OK";
		}

	
	}
	
}
